﻿
Namespace internalFunctions
    'parameters, i, any, input
    '            o, pointer<T>
    'return, bool, whether converting is success or not
    Public MustInherit Class convertor(Of T)
        Inherits internalFunction

        Public Class parameters
            Public Const i As String = "i"
            Public Const o As String = "o"
        End Class

        Protected MustOverride Function convertImpl(ByVal ctx As context, _
                                                    ByVal i As Object, ByRef rtn As T, _
                                                    ByVal it As typeDefination) As Boolean
        Protected MustOverride Function outputType() As typeDefination

        Private Shared m As iParametersMapping = Nothing

        Shared Sub New()
            initialMapping(m, parameters.i, parameters.o)
        End Sub

        Protected Sub New(ByVal name As String)
            MyBase.New(name, m)
        End Sub

        Protected Overloads Function invoke(ByVal ctx As context, ByVal ot As typeDefination, _
                                            ByRef output As bare_variable) As Boolean
            Dim i As bare_variable = Nothing
            i = ctx.findVariable(parameters.i)
            If i Is Nothing Then
                raiseError("expect parameter " + parameters.i, errorHandle.errorType.user)
                Return False
            Else
                Dim o As bare_variable = Nothing
                o = ctx.findVariable(parameters.o)
                If o Is Nothing Then
                    raiseError("expect parameter " + parameters.o, errorHandle.errorType.user)
                    Return False
                ElseIf Not o.variable().isPointerOf(ot) Then
                    raiseError("expect parameter " + parameters.o + " is pointer, " + _
                               "and elementType1 is match output type " + typeNaming(ot), errorHandle.errorType.user)
                    Return False
                Else
                    Dim rtn As T = Nothing
                    Dim rst As Boolean
                    rst = convertImpl(ctx, i.value(), rtn, i.variable().type())
                    If rst Then
                        If o.variable().elementType1() = typeDefination.var Then
                            convertor.cast(Of pointer(Of pointer(Of Object)))(o.value()).instance().setinstance(rtn)
                        Else
                            convertor.cast(Of pointer(Of pointer(Of T)))(o.value()).instance().setinstance(rtn)
                        End If
                        output = New bare_variable(typeDefination.bool, True)
                    Else
                        output = New bare_variable(typeDefination.bool, False)
                    End If
                    Return True
                End If
            End If
        End Function

        Protected NotOverridable Overrides Function invoke(ByVal ctx As context, _
                                                           ByRef output As bare_variable) As Boolean
            Return invoke(ctx, outputType(), output)
        End Function
    End Class

    'parameters, same as convertor
    'return, same as convertor
    'same below
    Public Class converttobool
        Inherits convertor(Of Boolean)

        Protected Overrides Function convertImpl(ByVal ctx As context, _
                                                 ByVal i As Object, ByRef rtn As Boolean, _
                                                 ByVal it As typeDefination) As Boolean
            Try
                rtn = Convert.ToBoolean(i)
            Catch
                raiseError("can not convert " + typeNaming(it) + " to boolean.", errorHandle.errorType.user)
                Return False
            End Try

            Return True
        End Function

        Public Sub New()
            MyBase.New("tobool")
        End Sub

        Protected Overrides Function outputType() As typeDefination
            Return typeDefination.bool
        End Function
    End Class

    Public Class converttoint
        Inherits convertor(Of Int64)

        Protected Overrides Function convertImpl(ByVal ctx As context, _
                                                 ByVal i As Object, ByRef rtn As Int64, _
                                                 ByVal it As typeDefination) As Boolean
            Try
                rtn = Convert.ToInt64(i)
            Catch
                raiseError("can not convert " + typeNaming(it) + " to int64.", errorHandle.errorType.user)
                Return False
            End Try

            Return True
        End Function

        Public Sub New()
            MyBase.New("toint")
        End Sub

        Protected Overrides Function outputType() As typeDefination
            Return typeDefination.int
        End Function
    End Class

    Public Class converttofloat
        Inherits convertor(Of Double)

        Protected Overrides Function convertImpl(ByVal ctx As context, _
                                                 ByVal i As Object, ByRef rtn As Double, _
                                                 ByVal it As typeDefination) As Boolean
            Try
                rtn = Convert.ToDouble(i)
            Catch
                raiseError("can not convert " + typeNaming(it) + " to double.", errorHandle.errorType.user)
                Return False
            End Try

            Return True
        End Function

        Public Sub New()
            MyBase.New("tofloat")
        End Sub

        Protected Overrides Function outputType() As typeDefination
            Return typeDefination.float
        End Function
    End Class

    Public Class converttostring
        Inherits convertor(Of String)

        Protected Overrides Function convertImpl(ByVal ctx As context, _
                                                 ByVal i As Object, ByRef rtn As String, _
                                                 ByVal it As typeDefination) As Boolean
            Try
                rtn = Convert.ToString(i)
            Catch
                raiseError("can not convert " + typeNaming(it) + " to string.", errorHandle.errorType.exclamation)
                Return False
            End Try

            Return True
        End Function

        Public Sub New()
            MyBase.New("tostring")
        End Sub

        Protected Overrides Function outputType() As typeDefination
            Return typeDefination.string
        End Function
    End Class

    Public Class converttovar
        Inherits convertor(Of Object)

        Protected Overrides Function convertImpl(ByVal ctx As context, _
                                                 ByVal i As Object, ByRef rtn As Object, _
                                                 ByVal it As typeDefination) As Boolean
            rtn = i
            Return True
        End Function

        Public Sub New()
            MyBase.New("tovar")
        End Sub

        Protected Overrides Function outputType() As typeDefination
            Return typeDefination.var
        End Function
    End Class

    Public Class convertstringtoint
        Inherits convertor(Of Int64)

        Public Shadows Class parameters
            Public Const base As String = "base"
        End Class

        Public Sub New()
            MyBase.New("stringtoint")
        End Sub

        Protected Overrides Function convertImpl(ByVal ctx As context, _
                                                 ByVal i As Object, ByRef rtn As Int64, _
                                                 ByVal it As typeDefination) As Boolean
            Dim base As Int64 = 0
            If Not ctx.findVariableInt(parameters.base, base) Then
                base = 10
            End If

            If Not convertor.toint64(Convert.ToString(i), rtn, base) Then
                raiseError("cannot convert " + Convert.ToString(i) + " to int64 with base " + Convert.ToString(base), _
                           errorHandle.errorType.user)
                Return False
            Else
                Return True
            End If
        End Function

        Protected Overrides Function outputType() As typeDefination
            Return typeDefination.int
        End Function
    End Class

    Public Class convertinttostring
        Inherits convertor(Of String)

        Public Shadows Class parameters
            Public Const format As String = "format"
        End Class

        Protected Overrides Function convertImpl(ByVal ctx As context, _
                                                 ByVal i As Object, ByRef rtn As String, _
                                                 ByVal it As typeDefination) As Boolean
            Dim ii As Int64
            If Not convertor.toint64(i, ii) Then
                raiseError("expect parameter " + convertor(Of String).parameters.i + " should be int.", _
                           errorHandle.errorType.user)
                Return False
            End If

            Dim format As String = Nothing
            If Not ctx.findVariableStr(parameters.format, format) Then
                format = Nothing
            End If

            If format Is Nothing Then
                rtn = Convert.ToString(ii)
            Else
                rtn = ii.ToString(format)
            End If
            Return True
        End Function

        Public Sub New()
            MyBase.New("inttostring")
        End Sub

        Protected Overrides Function outputType() As typeDefination
            Return typeDefination.string
        End Function
    End Class

    Public Class convertinttochar
        Inherits convertor(Of String)

        Protected Overrides Function convertImpl(ByVal ctx As context, ByVal i As Object, ByRef rtn As String, _
                                                 ByVal it As typeDefination) As Boolean
            Dim ii As Int64
            If Not convertor.toint64(i, ii) Then
                raiseError("expect parameter " + parameters.i + " should be int.", errorHandle.errorType.user)
                Return False
            End If
            Dim c As Char
            If convertor.tochar(ii, c) Then
                rtn = c
                Return True
            Else
                raiseError("cannot convert " + Convert.ToString(i) + " to char.", errorHandle.errorType.user)
                Return False
            End If
        End Function

        Public Sub New()
            MyBase.New("inttochar")
        End Sub

        Protected Overrides Function outputType() As typeDefination
            Return typeDefination.string
        End Function
    End Class

    Public Class convertchartoint
        Inherits convertor(Of Int64)

        Protected Overrides Function convertImpl(ByVal ctx As context, ByVal i As Object, ByRef rtn As Int64, _
                                                 ByVal it As typeDefination) As Boolean
            Dim c As Char
            Dim ii As String
            ii = Convert.ToString(i)
            If strlen(ii) > 0 Then
                c = ii(0)
            Else
                raiseError("expect parameter " + parameters.i + " should be a string with at least one char.", _
                            errorHandle.errorType.user)
                Return False
            End If
            Dim o As Int32
            If convertor.toint32(c, o) Then
                rtn = o
                Return True
            Else
                raiseError("cannot convert " + Convert.ToString(c) + " to int.", errorHandle.errorType.user)
                Return False
            End If
        End Function

        Public Sub New()
            MyBase.New("chartoint")
        End Sub

        Protected Overrides Function outputType() As typeDefination
            Return typeDefination.int
        End Function
    End Class
End Namespace